package com.android.lyricshow.ui;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.lang.ref.WeakReference;
import java.util.ArrayList;

import com.android.lyricshow.BuildConfig;
import com.android.lyricshow.bean.AlbumBean;
import com.android.lyricshow.until.AppUntil;
import com.android.lyricshow.until.LogPrint;

import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.TransitionDrawable;
import android.net.Uri;
import android.util.Log;
import android.widget.ImageView;

public class ImageWorker {
	
	private static final String TAG 		= "ImageWorker";
	
	private static final int FADE_IN_TIME 	= 200;
	
	private boolean mFadeInBitmap 			= true;
	
	private ImageCache.ImageCacheParams mImageCacheParams;
	 
	private Bitmap sDefaultBitmap			= null;
	
	protected boolean mPauseWork 			= false;
	
	private final Object mPauseWorkLock 	= new Object();
	
	private ImageCache mImageCache			= null;
	
	private Resources mResources			= null;
	
	private Context mContext				= null;
	
	private int mStartLoadLimit				= 0;
	private int mStopLoadLimit				= 0;
	
    public ImageWorker(Context context, ImageCache.ImageCacheParams cacheParams) {
    	
    	mContext	= context;
    	mResources 	= context.getResources();
    	
    	mImageCacheParams = cacheParams;
    	mImageCache = new ImageCache(mImageCacheParams);
    }
    
	public void setLoadLimit(int startLoadLimit,int stopLoadLimit){
		
		if(startLoadLimit > stopLoadLimit){
			return;
		}
		
		mStartLoadLimit	= startLoadLimit;
		mStopLoadLimit	= stopLoadLimit;
	}
	
	public void loadImage(int pos, long data, ImageView imageView){
		
		Bitmap bitmap = null;
		
		// Find bitmap by id
		if(mImageCache != null) {
            bitmap = mImageCache.findBitmapById(data);
        }
		
		if(bitmap != null){
			setImageBitmap(imageView, bitmap);	
		}else{
			final BitmapWorkerTask task	= new BitmapWorkerTask(pos, imageView);	
			final AsyncDrawable rawable = new AsyncDrawable(mResources, sDefaultBitmap, task);
			
			imageView.setImageDrawable(rawable);
			
			task.executeOnExecutor(AsyncTask.DUAL_THREAD_EXECUTOR, data);
		}
	}
	
    public void setImageFadeIn(boolean fadeIn) {
        mFadeInBitmap = fadeIn;
    }
    
    public void setDefaultImage(int resId) {
    	BitmapFactory.Options opts = new BitmapFactory.Options();
        //opts.inPreferredConfig = Bitmap.Config.RGB_565;   
    	sDefaultBitmap = BitmapFactory.decodeStream(mContext.getResources().openRawResource(resId), null, opts);
    }
    
    private static BitmapWorkerTask getBitmapWorkerTask(ImageView imageView) {
        if (imageView != null) {
            final Drawable drawable = imageView.getDrawable();
            if (drawable instanceof AsyncDrawable) {
                final AsyncDrawable asyncDrawable = (AsyncDrawable) drawable;
                return asyncDrawable.getBitmapWorkerTask();
            }
        }
        return null;
    }
    
    public void setPauseWork(boolean pauseWork) {
        synchronized (mPauseWorkLock) {
            mPauseWork = pauseWork;
            if (!mPauseWork) {
                mPauseWorkLock.notifyAll();
            }
        }
    }
	
	private class BitmapWorkerTask extends AsyncTask<Object, Void, Bitmap> {
		 
        private Object mData;
        private final WeakReference<ImageView> mViewRef;
        
        private int mPos = -1;
        
        public BitmapWorkerTask(int pos, ImageView imageView) {
        	mViewRef= new WeakReference<ImageView>(imageView);
            mPos	= pos;	
        }

        /**
         * Background processing.
         */
        @Override
        protected Bitmap doInBackground(Object... params) {
            if (BuildConfig.DEBUG) {
                Log.d(TAG, "doInBackground - starting work");
            }

            mData = params[0];
            final String dataString = String.valueOf(mData);
            Bitmap bitmap = null;

            // Wait here if work is paused and the task is not cancelled
            synchronized (mPauseWorkLock) {
                while (mPauseWork && !isCancelled()) {
                    try {
                        mPauseWorkLock.wait();
                    } catch (InterruptedException e) {}
                }
            }
            
            if(mStopLoadLimit != 0 && (mStartLoadLimit != mStopLoadLimit)
            	&& (mPos < mStartLoadLimit || mPos > mStopLoadLimit)){
                return null;
            }
         
            if(!isCancelled()){
            	bitmap = AppUntil.getBitmapFromDB(mContext, Long.parseLong(dataString), AppUntil.SIZE_SMALL);
            }
            
            if (bitmap != null && mImageCache != null) {
                mImageCache.addBitmapToCache(Long.parseLong(dataString), bitmap);
            }

            if (BuildConfig.DEBUG) {
                Log.d(TAG, "doInBackground - finished work");
            }

            return bitmap;
        }

        @Override
        protected void onPostExecute(Bitmap bitmap) {
            if (isCancelled()) {
                bitmap = null;
            }

            final ImageView imageView = getAttachedImageView();
            if (bitmap != null && imageView != null) {
                if (BuildConfig.DEBUG) {
                    Log.d(TAG, "onPostExecute - setting bitmap");
                }
                setImageBitmap(imageView, bitmap);
            }
        }

        @Override
        protected void onCancelled(Bitmap bitmap) {
            super.onCancelled(bitmap);
            synchronized (mPauseWorkLock) {
                mPauseWorkLock.notifyAll();
            }
        }

        /**
         * Returns the ImageView associated with this task as long as the ImageView's task still
         * points to this task as well. Returns null otherwise.
         */
        private ImageView getAttachedImageView() {
            final ImageView imageView = mViewRef.get();
            final BitmapWorkerTask bitmapWorkerTask = getBitmapWorkerTask(imageView);

            if (this == bitmapWorkerTask) {
                return imageView;
            }

            return null;
        }
	}
	 
	private static class AsyncDrawable extends BitmapDrawable {
        private final WeakReference<BitmapWorkerTask> bitmapWorkerTaskReference;
       
        public AsyncDrawable(Resources res, Bitmap bitmap, BitmapWorkerTask bitmapWorkerTask) {
            super(res, bitmap);
            bitmapWorkerTaskReference =
                new WeakReference<BitmapWorkerTask>(bitmapWorkerTask);
        }

        public BitmapWorkerTask getBitmapWorkerTask() {
            return bitmapWorkerTaskReference.get();
        }
	}
	
    private void setImageBitmap(ImageView imageView, Bitmap bitmap) {
        if (mFadeInBitmap) {
            // Transition drawable with a transparent drwabale and the final bitmap
            final TransitionDrawable td =
                    new TransitionDrawable(new Drawable[] {
                            new ColorDrawable(android.R.color.transparent),
                            new BitmapDrawable(mResources, bitmap)
                    });
            
            imageView.setImageDrawable(td);
            td.startTransition(FADE_IN_TIME);
        } else {
            imageView.setImageBitmap(bitmap);
        }
    }
}
